#ifndef __M_FMT_H__
#define __M_FMT_H__
#include "level.hpp"
#include "message.hpp"
#include <time.h>
#include <vector>
#include<cassert>
#include<sstream>
#include <memory>

namespace bitlog
{
    class FormatItem
    {
    public:
        using ptr = std::shared_ptr<FormatItem>;
        virtual void format(std::ostream &out,const LogMsg &msg) = 0;
    };

    class MsgFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << msg._payload;
        }
    };
    class LevelFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << LogLevel::toString(msg._level);
        }
    };
    class TimeFormatItem : public FormatItem//@@@@@@@@@@@@@@@@@@@@
    {
    public:
        TimeFormatItem(const std::string &fmt = "%H:%M:%S") : _time_fmt(fmt) {}
        void format(std::ostream &out,const LogMsg &msg) override
        {
            struct tm t;
            localtime_r(&msg._ctime, &t);//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
            char tmp[32] = {0};
            strftime(tmp, 31, _time_fmt.c_str(), &t);//@@@@@@@@@@@@@@@
            out << tmp;
        }

    private:
        std::string _time_fmt; //%H:%M:%S
    };
    class FileFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << msg._file;
        }
    };
    class LineFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << msg._line;
        }
    };
    class ThreadFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << msg._tid;
        }
    };
    class LoggerFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << msg._logger;
        }
    };
    class TabFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << "\t";
        }
    };
    class NLineFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << "\n";
        }
    };
    class OtherFormatItem : public FormatItem
    {
    public:
        OtherFormatItem(const std::string &str) : _str(str) {}
        void format(std::ostream &out,const LogMsg &msg) override
        {
            out << _str;
        }

    private:
        std::string _str;
    };

    /*
    %d表示日期，包含子格式{%H:%M:%S}
    %t表示线程ID
    %c 表示日志器名称
    %f 表示源码文件名
    %l 表示源码行号
    %p 表示日志级别
    %T 表示制表符缩进
    %m 表示主题消息
    %n 表示换行
    */
    class Formatter
    {
    public:
        using ptr=std::shared_ptr<Formatter>;
        Formatter(const std::string &pattern="[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n"):
        _pattern(pattern){
           assert(parsePattern());
                    
        }
        //对msg进行格式化
        std::string format(const LogMsg &msg){
            std::stringstream ss;
            format(ss,msg);
            return ss.str();
        }
        void format(std::ostream &out,const LogMsg &msg)
        {
            for(auto &item :_items){
              item->format(out,msg);
            }
        }
        private:
        //对格式化规则字符串进行解析
        bool parsePattern(){
            std::vector<std::pair<std::string,std::string>>fmt_order;
            size_t pos=0;
            std::string key,val;//感觉有问题
            while(pos<_pattern.size())
            {
                
                if(_pattern[pos]!='%')
                {
                     val.push_back(_pattern[pos++]);
                     continue;
                }
                //能到这代表pos位置就是%字符
                if(pos+1<_pattern.size()&&_pattern[pos+1]=='%')
                {
                    val.push_back('%');pos+=2;continue;
                }
                if(val.empty()==false) {
                  fmt_order.push_back(std::make_pair("",val));//other
                  val.clear();//@@@@@@@@@@@@@@@@@@@@@@@
                }


                //这时候是格式化字符串的处理
                pos+=1;//这一步后，指向格式化字符位置
                if(pos==_pattern.size())
                {
                    std::cout<<"%之后没有对应的格式化字符！\n";
                    return false;
                }
                key=_pattern[pos];
                pos+=1;//判断是否有花括号{
                
                if(pos<_pattern.size()&&_pattern[pos]=='{')
                {
                   
                    pos+=1;//这时pos指向{之后子规则的起始位置
                    while(pos<_pattern.size()&&_pattern[pos]!='}')
                    {
                       val.push_back(_pattern[pos++]);
                    }
                    if(pos==_pattern.size()){
                        std::cout<<"子规则{}匹配出错！\n";
                        return false;//没有找到}
                    }
                    pos+=1;
                }
                fmt_order.push_back(std::make_pair(key,val));
                key.clear();
                val.clear();
            }
            for(auto &it:fmt_order)
            {
                _items.push_back(createItem(it.first,it.second));
            }
            return  true;
        }
   
        //根据不同的格式化字符串创建不同的格式化子项对象
        FormatItem::ptr createItem(const std::string &key,const std::string &val){
            if(key=="d")return std::make_shared<TimeFormatItem>(val);
            if(key=="t")return std::make_shared<ThreadFormatItem>();
            if(key=="c")return std::make_shared<LoggerFormatItem>();
            if(key=="f")return std::make_shared<FileFormatItem>();
            if(key=="l")return std::make_shared<LineFormatItem>();
            if(key=="p")return std::make_shared<LevelFormatItem>();
            if(key=="T")return std::make_shared<TabFormatItem>();
            if(key=="m")return std::make_shared<MsgFormatItem>();
            if(key=="n")return std::make_shared<NLineFormatItem>();
            if(key=="") return  std::make_shared<OtherFormatItem>(val);
            std::cout<<"没有对应的格式化字符：%"<<key<<std::endl;
            abort();//程序异常退出@@@@@@@@@@@@@@@@@@@@@@@@@@@@
            return FormatItem::ptr();
        }
    private:
        std::string _pattern;//格式化规则字符串
        std::vector<FormatItem::ptr> _items;
    };

}

#endif